
#include <linux/fs.h>
#include <linux/mm.h>

#include "internal.h"

#include "tutorfs.h"

int __set_page_dirty_no_writeback(struct page *page)
{
	if (!PageDirty(page))
		return !TestSetPageDirty(page);
	return 0;
}

const struct address_space_operations tutorfs_aops = {
	.readpage	= simple_readpage,
	.write_begin	= simple_write_begin,
	.write_end	= simple_write_end,
	.set_page_dirty = __set_page_dirty_no_writeback,
};

ssize_t tutorfs_file_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos) {
	struct req_read qread;
	struct res_read sread;
	char path[256];

	printk("tutorfs_file_read called\n");

	if (get_dentry_path(path, 256, filp->f_dentry) < 0)
		return -1;

	// file read call
//	if (cc == 0) {
//		strcpy(buf, "asdasd");
//		ppos += 6;
//		cc = 1;
//		return 6;
//	}

	printk("len : %d\n", len);

	memset(&qread, 0, sizeof(qread));
	strcpy(qread.filepath, path);
	qread.pos = *ppos;
	qread.size = len > 256 ? 256 : len;

	printk("size : %d\n", qread.size);
	memset(&sread, 0, sizeof(sread));

	if (request_protocol(TYPE_REQ_READ, &qread, sizeof(qread), &sread, sizeof(sread), tutorfs_sock) < 0) {
		return -1;
	}

	if (sread.size < 0)
		return -1;
	printk("sread size : %d\n", sread.size);

	memcpy(buf + *ppos, sread.data, qread.size);

	return 0;
}

ssize_t tutorfs_file_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos) {
	char path[256];
	struct req_write rw;
	struct res_ok rok;

	printk("tutorfs_file_write called\n");

	if (get_dentry_path(path, 256, filp->f_dentry) < 0)
		return -1;

	memset(&rw, 0, sizeof(rw));
	rw.pos = *ppos;
	rw.size = len > 2048 ? 2048 : len;
	memcpy(rw.data, buf, rw.size);
	strcpy(rw.filepath, path);

	if (request_protocol(TYPE_REQ_WRITE, &rw, sizeof(rw), &rok, sizeof(rok), tutorfs_sock) < 0) {
		return -1;
	}

	if (rok.isok == 0)
		return -1;

	return do_sync_write(filp, buf, len, ppos);
}

const struct file_operations tutorfs_file_operations = {
	.read		= do_sync_read,
	.aio_read	= generic_file_aio_read,
	.write		= tutorfs_file_write,
	.aio_write	= generic_file_aio_write,
	.mmap		= generic_file_mmap,
	.fsync		= noop_fsync,
	.splice_read	= generic_file_splice_read,
	.splice_write	= generic_file_splice_write,
	.llseek		= generic_file_llseek,
};

const struct inode_operations tutorfs_file_inode_operations = {
	.setattr	= simple_setattr,
	.getattr	= simple_getattr,
};
